package com.foo.designpattern.interpreter;

import junit.framework.TestCase;

/**
 * com.foo.designpattern.interpreter
 * Created with IntelliJ IDEA.
 * Created by jiang on 2016-06-12 15:09.
 *
 * @Description 测试类：解释器模式(Interpreter)
 * 解释器模式：解释器模式是类的行为模式。给定一个语言之后，解释器模式可以定义出其文法的一种表示，并同时提供一个解释器。
 * 客户端可以使用这个解释器来解释这个语言中的句子。
 * <p/>
 * 解释器模式所涉及的角色如下：
 * 1、抽象表达(Expression)式角色：声明一个所有的具体表达式角色都需要实现的抽象接口。这个接口主要是一个interpret()方法，称作解释操作。
 * 2、终结符表达式(Terminal Expression)角色：实现了抽象表达式角色所需要的接口，主要是一个interpret()方法；文法中的每一个终结符都
 * 有一个具体终结表达式与之对应。比如，有一个简单的公式R=R1+R2,在里面R1和R2就是终结符，对应的解析R1和R2的解释器就是终结符表达式。
 * 3、非终结符表达式(Non Terminal Expression)角色：文法中的每一条规则都需要一个具体的非终结符表达式，非终结符表达式一般是文法中的
 * 运算符或者其他关键字，比如公式R=R1+R2中，"+"就是非终结符，解析"+"的解释器就是一个非终结符表达式。
 * 4、环境(Context)角色；这个角色的任务一般是用来存放文法中各个终结符所对应的具体值，比如R=R1+R2，我们给R1赋值100，给R2赋值200.
 * 这些信息需要存放到环境角色中，很多情况下我们使用Map来充当环境角色就足够了。
 * <p/>
 * 为了说明解释器模式的实现方法，本例给出一个最简单的文法和对应的解释器模式的实现，这就是模拟java语言中对布尔表达式进行操作和求值。
 * 在这个语言中终结符是布尔变量，也就是常量true和false。非终结符表达式包含运算符and，ro和not等布尔表达式。这个简单的文法如下：
 * Expression    ::= Constant|Variable|Or|And|Not
 * And           ::= Expression 'AND' Expression
 * Or            ::= Expression 'OR' Expression
 * Not           ::= 'NOT' Expression
 * Variable      ::= 任意标识符
 * Constant      ::= 'true'|'false'
 * <p/>
 * 解释器模式的优点：
 * 1、解释器是一个简单的语法分析工具，它最显著的优点就是扩展性，修改语法规则只需要修改相应的非终结符就可以了，
 * 若扩展语法，只需要增加非终结符类就可以了。
 * 解释器模式的缺点：
 * 1、解释器模式会引起类的膨胀，每个语法都要产生一个非终结符表达式，语法规则比较复杂时，可能产生大量的类文件，难以维护；
 * 2、解释器模式采用递归调用方法，它导致调试非常复杂；
 * 3、解释器由于使用了大量的循环和递归，所以当用于解析复杂、冗长的语法时，效率是难以忍受的。
 * <p/>
 * 解释器模式的适用场景：
 * 解释器模式并不是一种应用很广泛的模式，因为它特别适合用来解释语言，而在一般的软件系统中，内嵌一种语言的成本显然太高。
 * 但这种模式的出发点值得借鉴：如果一种特定类型的问题发生的频率足够高，那么可能就值得将该问题的实例表述为一个简单语言中的句子。
 * 这样，就可以构建一个解释器，该解释器通过解释这些句子来解决这些问题。
 * 由于解释器模式后期维护困难，尽量不要在重要模块中使用，在项目中，可以使用shell,JRuby,Groovy等脚本语言来代替解释器模式。
 * <p/>
 * 正则表达式引擎是一个解释器模式应用的很好的实例。
 * 搜索匹配一个模式的字符串是一个常见问题。正则表达式是描述字符串模式的一种标准语言。
 * 与其为每一个的模式都构造一个特定算法，不如使用一种通用的搜索算法来解释执行一个正则表达式，该正则表达式定义了待匹配字符串的集合。
 */

public class InterpreterTestCase extends TestCase {
    public void testInterpreter() {
        System.out.println("= = = = ↓↓↓解释器模式，测试开始↓↓↓ = = = =");
        Context ctx = new Context();
        Variable x = new Variable("x");
        Variable y = new Variable("y");
        Constant con = new Constant(true);
        ctx.assign(x, false);
        ctx.assign(y, true);

        Expression exp = new Or(new And(con, x), new And(y, new Not(x)));
        System.out.println("x = " + x.interpret(ctx));
        System.out.println("y = " + y.interpret(ctx));
        System.out.println(exp.toString() + " = " + exp.interpret(ctx));
        System.out.println("= = = = ↑↑↑解释器模式，测试结束↑↑↑ = = = =");
    }
}
